package com.swotxu.mall.product.web;

import com.swotxu.mall.product.entity.CategoryEntity;
import com.swotxu.mall.product.service.CategoryService;
import com.swotxu.mall.product.web.vo.Catelog2Vo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 默认资源前缀后缀
 * {@link org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties}
 * String prefix = "classpath:/templates/"
 * String suffix = ".html";
 *
 * @Date: 2021/1/18 23:21
 * @Author: swotXu
 */
@Slf4j
@Controller
public class IndexController {

    @Autowired
    CategoryService categoryService;
    @Autowired
    RedissonClient redissonClient;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @GetMapping({"/", "index", "index.html"})
    public String index(Model model) {
        // 查出所有一级分类数据，并返回首页
        List<CategoryEntity> categoryEntityList =  categoryService.getLevel1Categorys();
        model.addAttribute("categorys", categoryEntityList);
        return "index";
    }

    @GetMapping("/index/json/catalogjson")
    @ResponseBody
    public Object getCatelogJson() {
        Map<String, List<Catelog2Vo>> map = categoryService.getCatelogJson();
        return map;
    }

    @GetMapping("/hello")
    @ResponseBody
    public String hello() {
        RLock lock = redissonClient.getLock("my_lock");

        // lock.lock(); // 阻塞式等待，默认加锁30s
        lock.lock(10, TimeUnit.SECONDS);    // 10s自动解锁 - 自动解锁时间一定要大于业务执行时间 （建议使用）
        try {
            log.info("加锁成功！{}", Thread.currentThread().getName());
            TimeUnit.SECONDS.sleep(20);
        } catch (InterruptedException e) {
            log.warn("睡眠失败", e);
        } finally {
            log.info("释放锁！{}", Thread.currentThread().getName());
            lock.unlock();
        }
        return "hello word";
    }
    @GetMapping("/write")
    @ResponseBody
    public String writeValue() {
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("rw_lock");
        RLock wLock = rwLock.writeLock();

        wLock.lock();
        String id = "";
        try {
            id = UUID.randomUUID().toString();
            TimeUnit.SECONDS.sleep(20);
            stringRedisTemplate.opsForValue().set("readWriteValue", id);
        } catch (InterruptedException e) {
            log.warn("睡眠失败", e);
        } finally {
            wLock.unlock();
        }
        return id;
    }

    @GetMapping("/read")
    @ResponseBody
    public String readValue() {
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("rw_lock");
        RLock rLock = rwLock.readLock();

        rLock.lock();
        String id = "";
        try {
            TimeUnit.SECONDS.sleep(8);
            id = stringRedisTemplate.opsForValue().get("readWriteValue");
        } catch (Exception e) {
            log.warn("读取失败", e);
        } finally {
            rLock.unlock();
        }
        return id;
    }

    // 模拟车库停车，测试信号量 Semaphore
    @GetMapping("/park")
    @ResponseBody
    public String park() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("park_lock");
        semaphore.acquire(); // 获取一个信号，若无信号则阻塞等待，占一个车位
        return "ok!";
    }
    @GetMapping("/go")
    @ResponseBody
    public String go() {
        RSemaphore semaphore = redissonClient.getSemaphore("park_lock");
        semaphore.release(); // 释放一个信号
        return "ok!";
    }

    // 模拟闭锁 ，学校放假锁门，需要等全部班级没人了，才能锁门
    @GetMapping("/lockDoor")
    @ResponseBody
    public String lockDoor() throws InterruptedException {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("door_lock");
        countDownLatch.trySetCount(5);
        countDownLatch.await();
        return "放假了!";
    }
    @GetMapping("/gogogo/{id}")
    @ResponseBody
    public String gogogo(@PathVariable("id") Long id) {
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("door_lock");
        countDownLatch.countDown();
        return id + "班的人都走了!";
    }
}
